package com.ittest.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.ittest.entity.FillData;
import com.ittest.entity.FillDataHour;
import com.ittest.entity.IdUtil;
import com.ittest.entity.RainInfo;
import lombok.extern.log4j.Log4j2;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;


@Log4j2
@EnableScheduling
@Component
public class ScheduleRain {
    private static final String watherUrl = "http://www.nmc.cn/rest/weather?stationid=";

    //天气预报信息每天7点发布，7.25去请求数据
    @Scheduled(cron = "0 35 7 * * ?")
//    @PostConstruct
    public void getRainForecast() throws InterruptedException {
        log.info("开始获取降雨量预报信息");
        //获取沿线城市信息,沿途城市包含北延
        HashMap<String,String> cityInfos = IdUtil.hashMap;
        HashMap<String,String> cityNewInfos = IdUtil.hashCityMap;
        cityInfos.putAll(cityNewInfos);
        List<FillData> fillDataList = new ArrayList<>();
        //获取区/县的数据
        //重试机制，先重试5次
        int maxRetries = 20;
        int retryCount = 0;
        boolean success = false;

        while (!success && retryCount < maxRetries) {
            try {
                cityInfos.forEach((cityName, code) -> {
                    FillData fillData = processCityWeatherData(cityName, code);
                    fillDataList.add(fillData);
                    try {
                        Thread.sleep(new Random().nextInt(1000)+1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {

                System.out.println("失败！"+e);
            }
            if (fillDataList.size() <71){
                // 处理异常
                retryCount++;
                System.out.println("获取降雨量数据不是71个城市！第"+retryCount+"次重试！城市是"+fillDataList.size());
                Thread.sleep(new Random().nextInt(1000)+1);
                fillDataList.clear();

            } else {
                success =true;
            }
        }
        //对地区的微山县，临清市和沛县置顶一下
        List<FillData> newList = new ArrayList<>();
        Iterator<FillData> iterator = fillDataList.iterator();
        while (iterator.hasNext()) {
            FillData fillData = iterator.next();
            if ("临清市".equals(fillData.getRegion()) ||
                    "微山县".equals(fillData.getRegion()) ||
                    "沛县".equals(fillData.getRegion())) {
                newList.add(fillData);
                iterator.remove(); // 使用Iterator的remove方法安全删除
            }
        }
        //排序县/区的数据 也包括市
        Collections.sort(fillDataList, new Comparator<FillData>() {
            @Override
            public int compare(FillData o1, FillData o2) {
                return new BigDecimal(o2.getRainSum()).compareTo(new BigDecimal(o1.getRainSum()));
            }
        });
        fillDataList.addAll(0, newList);
        ReadeExcelTemplate.exportDataByAnnotation(fillDataList);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH");
        String format = dateFormat.format(new Date());
        StringBuilder stringBuilder  = new StringBuilder();
        stringBuilder.append("'\'").append(format).append("点前24小时降雨量数据统计").append(".xlsx");
        try {
            for (String address : IdUtil.yxAddressList) {
                MailUtils.sendMail(stringBuilder.toString(),address);

            }
        } catch (Exception e){
            log.error(e);
        }
    }

    @Scheduled(cron = "0 35 15 * * ?")
//    @PostConstruct
    public void getRainForecast1() throws InterruptedException {
        log.info("开始获取降雨量预报信息");
        //获取沿线城市信息,沿途城市包含北延
        HashMap<String,String> cityInfos = IdUtil.hashMap;
        HashMap<String,String> cityNewInfos = IdUtil.hashCityMap;
        cityInfos.putAll(cityNewInfos);
        List<FillData> fillDataList = new ArrayList<>();
        //获取区/县的数据
        //重试机制，先重试5次
        int maxRetries = 20;
        int retryCount = 0;
        boolean success = false;

        while (!success && retryCount < maxRetries) {
            try {
                cityInfos.forEach((cityName, code) -> {
                    FillData fillData = processCityWeatherData(cityName, code);
                    fillDataList.add(fillData);
                    try {
                        Thread.sleep(new Random().nextInt(1000)+1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {

                System.out.println("失败！"+e);
            }
            if (fillDataList.size() <71){
                // 处理异常
                retryCount++;
                System.out.println("获取降雨量数据不是71个城市！第"+retryCount+"次重试！城市是"+fillDataList.size());
                Thread.sleep(new Random().nextInt(1000)+1);
                fillDataList.clear();

            } else {
                success =true;
            }
        }

        //对地区的微山县，临清市和沛县置顶一下
        List<FillData> newList = new ArrayList<>();
        Iterator<FillData> iterator = fillDataList.iterator();
        while (iterator.hasNext()) {
            FillData fillData = iterator.next();
            if ("临清市".equals(fillData.getRegion()) ||
                    "微山县".equals(fillData.getRegion()) ||
                    "沛县".equals(fillData.getRegion())) {
                newList.add(fillData);
                iterator.remove(); // 使用Iterator的remove方法安全删除
            }
        }

        //排序县/区的数据 也包括市
        Collections.sort(fillDataList, new Comparator<FillData>() {
            @Override
            public int compare(FillData o1, FillData o2) {
                return new BigDecimal(o2.getRainSum()).compareTo(new BigDecimal(o1.getRainSum()));
            }
        });
        fillDataList.addAll(0, newList);
        ReadeExcelTemplate.exportDataByAnnotation(fillDataList);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH");
        String format = dateFormat.format(new Date());
        StringBuilder stringBuilder  = new StringBuilder();
        stringBuilder.append("'\'").append(format).append("点前24小时降雨量数据统计").append(".xlsx");
        try {
            for (String address : IdUtil.yxAddressList) {
                MailUtils.sendMail(stringBuilder.toString(),address);

            }
        } catch (Exception e){
            log.error(e);
        }
    }


    /**
     * 1小时降雨量统计
     * @throws InterruptedException
     */
//    @PostConstruct 0 38 0/1 * * ?
//    @Scheduled(cron = "0 38 0/1 * * ?")
    public void getHourRainForecast() throws InterruptedException {
        log.info("开始获取小时降雨量预报信息");
        //获取沿线城市信息,沿途城市包含北延
        HashMap<String,String> cityInfos = IdUtil.hashMap;
        HashMap<String,String> cityNewInfos = IdUtil.hashCityMap;
        cityInfos.putAll(cityNewInfos);
        List<FillDataHour> fillDataList = new ArrayList<>();
        //获取区/县的数据
        //重试机制，先重试20次
        int maxRetries = 20;
        int retryCount = 0;
        boolean success = false;

        while (!success && retryCount < maxRetries) {
            try {
                cityInfos.forEach((cityName, code) -> {
                    FillDataHour fillData = processCityWeatherDataHour(cityName, code);
                    fillDataList.add(fillData);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
                System.out.println("失败！"+e);
            }
            if (fillDataList.size() <73){
                // 处理异常
                retryCount++;
                System.out.println("获取降雨量数据不是73个城市！第"+retryCount+"次重试！城市是"+fillDataList.size());
                Thread.sleep(3000);
                fillDataList.clear();

            } else {
                success =true;
            }
        }
        //排序县/区的数据 也包括市
        Collections.sort(fillDataList, new Comparator<FillDataHour>() {
            @Override
            public int compare(FillDataHour o1, FillDataHour o2) {
                return new BigDecimal(o2.getRainSum()).compareTo(new BigDecimal(o1.getRainSum()));
            }
        });

        ReadeExcelTemplate.exportDataByAnnotationHour(fillDataList);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH");
        String format = dateFormat.format(new Date());
        StringBuilder stringBuilder  = new StringBuilder();
        stringBuilder.append("'\'").append(format).append("点前1小时降雨量数据统计").append(".xlsx");
        try {
            //发送短信
            for (String address : IdUtil.yxAddressList) {
                MailUtils.sendMail(stringBuilder.toString(),address);

            }
        } catch (Exception e){
            log.error(e);
        }
    }
    /**
     * 12小时降雨量统计
     * @throws InterruptedException
     */
//    @PostConstruct
//    @Scheduled(cron = "0 35 15 * * ?")
    public void getTwoSixHourRainForecast() throws InterruptedException {
        log.info("开始获取12小时降雨量预报信息");
        //获取沿线城市信息,沿途城市包含北延
        HashMap<String,String> cityInfos = IdUtil.hashMap;
        HashMap<String,String> cityNewInfos = IdUtil.hashCityMap;
        cityInfos.putAll(cityNewInfos);
        List<FillDataHour> fillDataList = new ArrayList<>();
        //获取区/县的数据
        //重试机制，先重试20次
        int maxRetries = 20;
        int retryCount = 0;
        boolean success = false;

        while (!success && retryCount < maxRetries) {
            try {
                cityInfos.forEach((cityName, code) -> {
                    FillDataHour fillData = processCityWeatherDataTwoSixHour(cityName, code);
                    fillDataList.add(fillData);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
                System.out.println("失败！"+e);
            }
            if (fillDataList.size() <73){
                // 处理异常
                retryCount++;
                System.out.println("获取降雨量数据不是73个城市！第"+retryCount+"次重试！城市是"+fillDataList.size());
                Thread.sleep(3000);
                fillDataList.clear();

            } else {
                success =true;
            }
        }
        //排序县/区的数据 也包括市
        Collections.sort(fillDataList, new Comparator<FillDataHour>() {
            @Override
            public int compare(FillDataHour o1, FillDataHour o2) {
                return new BigDecimal(o2.getRainSum()).compareTo(new BigDecimal(o1.getRainSum()));
            }
        });

        ReadeExcelTemplate.exportDataByAnnotationHour(fillDataList);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH");
        String format = dateFormat.format(new Date());
        StringBuilder stringBuilder  = new StringBuilder();
        stringBuilder.append("'\'").append(format).append("点前1小时降雨量数据统计").append(".xlsx");
        try {
            //发送短信
            for (String address : IdUtil.yxAddressList) {
                MailUtils.sendMail(stringBuilder.toString(),address);

            }
        } catch (Exception e){
            log.error(e);
        }
    }




    //处理城市天气数据
    public static FillData processCityWeatherData(String cityName, String cityCode) {
        //获取天气数据
        JSONObject weatherData = getWeatherData(cityName,cityCode);
        //解析天气数据
        return handleRealWeatherData(cityName, weatherData);
    }
    //处理城市天气数据
    public static FillDataHour processCityWeatherDataHour(String cityName, String cityCode) {
        //获取天气数据
        JSONObject weatherData = getWeatherData(cityName,cityCode);
        //解析天气数据
        return handleHourRealWeatherData(cityName, weatherData);
    }
    //处理城市天气数据
    public static FillDataHour processCityWeatherDataTwoSixHour(String cityName, String cityCode) {
        //获取天气数据
        JSONObject weatherData = getWeatherData(cityName,cityCode);
        //解析天气数据
        return handleTwoSixHourRealWeatherData(cityName, weatherData);
    }

    //处理城市天气数据
    public static JSONObject getWeatherData(String cityName, String cityCode) {
        try {
            URL url = new URL(watherUrl + cityCode);
            HttpURLConnection connection = createHttpURLConnection(url);
            connection.setConnectTimeout(10000); // 15 seconds
            connection.setReadTimeout(10000);
            //重试机制，先重试5次
            int maxRetries = 20;
            int retryCount = 0;
            boolean success = false;

            while (!success && retryCount < maxRetries) {
                try {
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        try (InputStreamReader reader = new InputStreamReader(connection.getInputStream())) {
                            Gson gson = new Gson();
                            return gson.fromJson(reader, JSONObject.class);
                        }
                    }
                    success =true;
                } catch (Exception e) {
                    // 处理异常
                    retryCount++;
                    System.out.println("获取降雨量失败！第"+retryCount+"次重试！城市是"+cityName);
                    Thread.sleep(3000);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static HttpURLConnection createHttpURLConnection(URL url) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        return connection;
    }

    /**
     * 统计二十四小时降雨量
     * @param cityName
     * @param data
     * @return
     */
    public static FillData handleRealWeatherData(String cityName, JSONObject data) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        // 获取当前时间
        Calendar cal = Calendar.getInstance();
        // 将分钟和秒钟清零
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        String newDate = dateFormat.format(cal.getTime());
        JSONArray jsonArray = data.getJSONObject("data").getJSONArray("passedchart");
        FillData fillData = new FillData();
        List<RainInfo> list = jsonArray.toJavaList(RainInfo.class);
        //如果统计的不是当前时间之前的24小时，则数据不对，统计出去
        StringBuilder builder = new StringBuilder();
        if (list.size() == 24){
            String endTime = list.get(0).getTime();
            builder.append(list.get(23).getTime()).append("-").append(endTime);
            if (!newDate.equals(endTime)){
                fillData.setRemark("降雨量统计异常，可能存在误差，请仔细核对！");
            }else {
                fillData.setRemark("正常");
            }
        }
        fillData.setDate(builder.toString());

        //统计每小时段的降雨量详情
        StringBuilder rainHourDetail = new StringBuilder();
        for (RainInfo rainInfo : list) {
            rainHourDetail.append(rainInfo.getTime()).append("前1小时降雨量统计为").append(rainInfo.getRain1h()).append('\n');
        }
        fillData.setHourInfo(rainHourDetail.toString());
        BigDecimal decimal = new BigDecimal(0);
        for (RainInfo rainInfo : list) {
            if (!"9999.0".equals(rainInfo.getRain1h())) {
                decimal = decimal.add(new BigDecimal(rainInfo.getRain1h()));
            }
        }
        fillData.setRainSum(decimal.toString());
        String[] split = cityName.split("-");
        fillData.setProvince(split[0]);
        fillData.setCity(split[1]);
        if (split.length == 3){
            fillData.setRegion(split[2]);
        } else {
            fillData.setRegion("-");
        }
        return fillData;
    }
    public static FillDataHour handleHourRealWeatherData(String cityName, JSONObject data) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        // 获取当前时间
        Calendar cal = Calendar.getInstance();
        // 将分钟和秒钟清零
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        String newDate = dateFormat.format(cal.getTime());
        JSONArray jsonArray = data.getJSONObject("data").getJSONArray("passedchart");
        FillDataHour fillData = new FillDataHour();
        List<RainInfo> list = jsonArray.toJavaList(RainInfo.class);
        //如果统计的不是当前时间之前的24小时，则数据不对，统计出去
        StringBuilder builder = new StringBuilder();
        if (list.size() == 24){
            String endTime = list.get(0).getTime();
            builder.append(list.get(1).getTime()).append("-").append(endTime);
            if (!newDate.equals(endTime)){
                fillData.setRemark("降雨量统计异常，可能存在误差，请仔细核对！");
            }else {
                fillData.setRemark("正常");
            }
        }
        fillData.setDate(builder.toString());
        BigDecimal decimal = new BigDecimal(0);
        List<RainInfo> hourList = new ArrayList<>();
        hourList.add(list.get(0));
        for (RainInfo rainInfo : hourList) {
            if (!"9999.0".equals(rainInfo.getRain1h())) {
                decimal = decimal.add(new BigDecimal(rainInfo.getRain1h()));
            }
        }
        fillData.setRainSum(decimal.toString());
        String[] split = cityName.split("-");
        fillData.setProvince(split[0]);
        fillData.setCity(split[1]);
        if (split.length == 3){
            fillData.setRegion(split[2]);
        } else {
            fillData.setRegion("-");
        }
        return fillData;
    }
    public static FillDataHour handleTwoSixHourRealWeatherData(String cityName, JSONObject data) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        // 获取当前时间
        Calendar cal = Calendar.getInstance();
        // 将分钟和秒钟清零
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        String newDate = dateFormat.format(cal.getTime());
        JSONArray jsonArray = data.getJSONObject("data").getJSONArray("passedchart");
        FillDataHour fillData = new FillDataHour();
        List<RainInfo> list = jsonArray.toJavaList(RainInfo.class);
        //如果统计的不是当前时间之前的24小时，则数据不对，统计出去
        StringBuilder builder = new StringBuilder();
        if (list.size() == 24){
            String endTime = list.get(0).getTime();
            builder.append(list.get(11).getTime()).append("-").append(endTime);
            if (!newDate.equals(endTime)){
                fillData.setRemark("降雨量统计异常，可能存在误差，请仔细核对！");
            }else {
                fillData.setRemark("正常");
            }
        }
        fillData.setDate(builder.toString());
        BigDecimal decimal = new BigDecimal(0);
        List<RainInfo> hourList = new ArrayList<>();
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (RainInfo rainInfo : list) {
            atomicInteger.addAndGet(1);
            if (!(atomicInteger.get() > 12)){
                hourList.add(rainInfo);
            }
        }
        for (RainInfo rainInfo : hourList) {
            if (!"9999.0".equals(rainInfo.getRain1h())) {
                decimal = decimal.add(new BigDecimal(rainInfo.getRain1h()));
            }
        }
        fillData.setRainSum(decimal.toString());
        String[] split = cityName.split("-");
        fillData.setProvince(split[0]);
        fillData.setCity(split[1]);
        if (split.length == 3){
            fillData.setRegion(split[2]);
        } else {
            fillData.setRegion("-");
        }
        return fillData;
    }

    public static void main(String[] args) {

    }

}
